﻿#define RELEASE

using AxZWANPHONELib;
using RestAPI;
using System;
using System.Threading.Tasks;
using LitJson;
using TopVisionLog;
using System.Threading;
using TopVisionVideoStream.Models;

namespace TopVisionVideoStream
{
    public static class Configuration
    {
        /// <summary>
        /// OCX控件对象
        /// </summary>
        public static AxZwanPhone Core = null;

        public static bool IsInited = false;

        #region 配置文件

        //程序环境
        public static string AppPath;

#if !RELEASE
        public static string iniZwanphone = @"D:\lite_ocx\ocx_pc_lib\release\zwanphone.ini";
#else
        public static string iniZwanphone = AppDomain.CurrentDomain.BaseDirectory + @"\bin\zwanphone.ini";
#endif
        //public static string iniZwanphone = AppDomain.CurrentDomain.BaseDirectory + @"\bin\zwanphone.ini";

        #endregion

        // Account info
        public static string Account;
        public static string Password;
        public static string CompanyID;
        public static string CompanyKey;

        // Login / out
        /// <summary>
        /// 账号登录尝试次数
        /// </summary>
        public static int retry = 3;
        /// <summary>
        /// 账号登录尝试计数
        /// </summary>
        public static int retryCount;
        /// <summary>
        /// 登录标识
        /// </summary>
        public static bool IsLoged = false;

        // Conf
        static int GetAccountStatusTimeout = 1000;
        public static string CallingID = "";
        public static CallStatusType CallStatus = CallStatusType.None;

        // 企业成员信息
        public static bool CompanyMemberEnable = true;
        // 多人会议
        public static bool ConfMemberEnable = true;

        // Server        
        public static ServerType _ServerType;

        public static string topvision_api = "";

        public static string UploadAddress = "";

        public static string photoAddress = "";

        #region 方法

        public static void UpdateAccountInformation(string account, string password)
        {
            Account = account;
            Password = password;
        }

        public static void UpdateCompanyInformation(string companyID, string companyKey)
        {
            CompanyID = companyID;
            CompanyKey = companyKey;
        }

        /// <summary>
        /// 通过API请求获取企业ID和密钥
        /// </summary>
        /// <param name="account">登录的账号</param>
        /// <param name="password">登录的密码</param>
        public static void UpdateCompanyInformationFormServer(string account, string password)
        {
            if (string.IsNullOrEmpty(account) | string.IsNullOrEmpty(password))
            {
                string log = "account or password is null";
                Console.WriteLine(log);
                TVLog.WriteLine(log);
                return;
            }

            MQuerycompanyinfo mqinfo = new MQuerycompanyinfo(account, password);

            mqinfo.Call(MQuerycompanyinfoResponse);
        }
        public static void UpdateCompanyInformationFormServer()
        {
            UpdateCompanyInformationFormServer(Account, Password);
        }
        /// <summary>
        /// 接口回调
        /// </summary>
        /// <param name="response"></param>
        private static void MQuerycompanyinfoResponse(string response)
        {
            try
            {
                Querycompanyinfo qJson = JsonMapper.ToObject<Querycompanyinfo>(response);

                if (qJson != null)
                {
                    CompanyID = qJson.companyid;
                    CompanyKey = qJson.password;
                    RestAPICommon.KEY = qJson.password;
                }
            }
            catch (Exception ex)
            {
                CompanyID = "";
                CompanyKey = "";
                RestAPICommon.KEY = "";
            }
        }
        public static void GetAgentstatus(RestAPICommon.GetPostResponseHandler result)
        {
            MGetagentstatus mgs = new MGetagentstatus(CompanyID, "");
            mgs.Call(result);
        }

        // 企业成员信息 线程

        public delegate void ERRORCompanyMembersHandler();
        public static event ERRORCompanyMembersHandler ERRORCompanyMembers;

        private static Task TaskUpdateCompanyMembersInfo;
        private static CancellationTokenSource ctsTaskUpdateCompanyMembersInfo;
        public static CompanyMembers _CompanyMembers;
        private static int errComMember;


        public async static void UpdateCompanyMembers()
        {
            //if (!(bool)TaskUpdateCompanyMembersInfo?.IsCompleted)
            //{
            //    ctsTaskUpdateCompanyMembersInfo.Cancel();
            //}

            if (!CompanyMemberEnable) return;

            await UpdateCompanyMembersCancel();

            ctsTaskUpdateCompanyMembersInfo = new CancellationTokenSource();

            TVLog.WriteLine("更新企业成员信息 ====================");
#if DEBUG
            Console.WriteLine("更新企业成员信息 ====================");
#endif

            TaskUpdateCompanyMembersInfo = Task.Factory.StartNew(UpdateCompanyMembersHttp, ctsTaskUpdateCompanyMembersInfo.Token);
        }

        private static void UpdateCompanyMembersHttp()
        {
            MGetagentstatus mgs = new MGetagentstatus(CompanyID, "");
            while (!ctsTaskUpdateCompanyMembersInfo.IsCancellationRequested)
            {
                var ret = mgs.Call(UpdateCompanyMembersInfoResult);
                if (ret == WebRequestError.类型错误) UpdateCompanyMembersInfoResult(null);
                TaskUpdateCompanyMembersInfo.Wait(1000);
            }
            ctsTaskUpdateCompanyMembersInfo.Dispose();
            ctsTaskUpdateCompanyMembersInfo = null;
        }

        private async static void UpdateCompanyMembersInfoResult(string response)
        {
            try
            {
                if (string.IsNullOrEmpty(response)) throw new Exception("response is null");

                _CompanyMembers = LitJson.JsonMapper.ToObject<CompanyMembers>(response);

                errComMember = 0;
            }
            catch (Exception ex)
            {
                TVLog.WriteLine("Get Agent Status err : " + ex.Message + " \r\n" + response);
#if DEBUG
                Console.WriteLine("Get Agent Status err : " + ex.Message + " \r\n" + response);
#endif
                errComMember++;

                if (errComMember > maxRetry)
                {
                    //await UpdateCompanyMembersCancel();

                    await Task.Delay(170);

                    errComMember = 0;

                    if (ERRORCompanyMembers != null)
                    {
                        ERRORCompanyMembers.Invoke();
                    }
                }
            }
        }

        public async static Task UpdateCompanyMembersCancel()
        {
            if (ctsTaskUpdateCompanyMembersInfo != null)
            {
                TVLog.WriteLine("准备取消更新企业成员信息 ====================");
#if DEBUG
                Console.WriteLine("准备取消更新企业成员信息 ====================");
#endif

                ctsTaskUpdateCompanyMembersInfo.Cancel();

                TVLog.WriteLine("取消更新企业成员信息 : " + ctsTaskUpdateCompanyMembersInfo.IsCancellationRequested + " ====================");
#if DEBUG
                Console.WriteLine("取消更新企业成员信息 : " + ctsTaskUpdateCompanyMembersInfo.IsCancellationRequested + " ====================");
#endif

                while (!TaskUpdateCompanyMembersInfo.IsCompleted)
                {
                    await Task.Delay(100);
                }
            }

            return;
        }

        // ===================================================================================================

        // 会议成员信息 线程

        public delegate void ERRORUpdateConfInfoHandler();
        public static event ERRORUpdateConfInfoHandler ERRORUpdateConfInfo;

        private static Task TaskUpdateConfMemberInfo;
        private static CancellationTokenSource ctsTaskUpdateConfMemberInfo;
        public static VideoConfMembers _VideoConfMembers;
        private static int errConfCallCount;
        private static int maxRetry = 5;

        public static void UpdateVideoConfMembers()
        {
            if (!ConfMemberEnable) return;

            UpdateVideoConfMembersCancel();

            ctsTaskUpdateConfMemberInfo = new CancellationTokenSource();
            TaskUpdateConfMemberInfo = Task.Factory.StartNew(UpdateVideoConfMembersHttp, ctsTaskUpdateConfMemberInfo.Token);

        }

        private static void UpdateVideoConfMembersHttp()
        {
            WebVideoConfMemberInfo wvcmInfo = new WebVideoConfMemberInfo(Configuration.CompanyID, Model_VideoConferenc.curCCR.confid);
            TVLog.WriteLine("更新会议成员信息 ====================");
#if DEBUG
            Console.WriteLine("更新会议成员信息 ====================");
#endif

            while (!ctsTaskUpdateConfMemberInfo.IsCancellationRequested)
            {
                var ret = wvcmInfo.Call(UpdateVideoConfMembersResult);
                //if (ret == WebRequestError.类型错误)
                //    UpdateVideoConfMembersResult(null);

                TaskUpdateConfMemberInfo.Wait(1000);
            }

            ctsTaskUpdateConfMemberInfo.Dispose();
            ctsTaskUpdateConfMemberInfo = null;
        }

        private static void UpdateVideoConfMembersResult(string response)
        {
            try
            {
                _VideoConfMembers = JsonMapper.ToObject<VideoConfMembers>(response);

                errConfCallCount = 0;
            }
            catch (Exception ex)
            {
                TVLog.WriteLine("Member Status err : " + ex.Message + "\r\n" + response);
#if DEBUG
                Console.WriteLine("Member Status err : " + ex.Message + "\r\n" + response);
#endif
                errConfCallCount++;

                _VideoConfMembers = null;

                if (errConfCallCount > maxRetry)
                {
                    //UpdateVideoConfMembersCancel();

                    errConfCallCount = 0;

                    if (ERRORUpdateConfInfo != null)
                    {
                        ERRORUpdateConfInfo.Invoke();
                    }
                }
            }
        }

        public static void UpdateVideoConfMembersCancel()
        {
            if (ctsTaskUpdateConfMemberInfo != null)
            {
                TVLog.WriteLine("准备取消更新会议成员信息 ====================");
#if DEBUG
                Console.WriteLine("准备取消更新会议成员信息 ====================");
#endif

                ctsTaskUpdateConfMemberInfo.Cancel();

                TVLog.WriteLine("取消更新会议成员信息 : " + ctsTaskUpdateConfMemberInfo.IsCancellationRequested + " ====================");
#if DEBUG
                Console.WriteLine("取消更新会议成员信息 : " + ctsTaskUpdateConfMemberInfo.IsCancellationRequested + " ====================");
#endif
                _VideoConfMembers = null;
            }
        }

        // ===================================================================================================


        static CallStatusType tmpCallStatus = CallStatusType.Failed;
        public static async Task<CallStatusType> GetAccountStatusAsync(string account)
        {
            try
            {
                TVLog.WriteLine("Calling ID:" + account);

                TVLog.WriteLine("CompanyID:" + CompanyID);

                if (CompanyID == null || CompanyID == "")
                {
                    return CallStatusType.Failed;
                }

                tmpCallStatus = CallStatusType.Checking;

                TVLog.WriteLine("Loading Account Data:");

                MGetagentstatus mgas = new MGetagentstatus(CompanyID, account);

                mgas.Call(GetAgentstatusResponse);

                int timer = 0;

                while (tmpCallStatus == CallStatusType.Checking)
                {
                    await Task.Delay(10);

                    timer += 10;

                    if (timer >= GetAccountStatusTimeout)
                    {
                        tmpCallStatus = CallStatusType.Failed;
                        break;
                    }
                }

                return tmpCallStatus;
            }
            catch (Exception ex)
            {
                TVLog.WriteLine("Error:" + ex.Message);
                return CallStatusType.Failed;
            }
        }

        private static void GetAgentstatusResponse(string response)
        {
            TVLog.WriteLine("Account Status:" + response);

            try
            {
                AgentStatus agentstatus = null;

                if (response.StartsWith("{"))
                    agentstatus = JsonMapper.ToObject<AgentStatus>(response);

                if (agentstatus == null)
                {
                    tmpCallStatus = CallStatusType.Failed;
                    return;
                }

                if (agentstatus.agentinfo == null || agentstatus.agentinfo.Count == 0)
                {
                    tmpCallStatus = CallStatusType.None;
                    return;
                }

                var agentStatus = (AgentStatusType)(int.Parse(agentstatus.agentinfo[0].status.Trim()));

                switch (agentStatus)
                {
                    case AgentStatusType.Failed:
                        tmpCallStatus = CallStatusType.Failed;
                        break;
                    case AgentStatusType.Checking:
                        tmpCallStatus = CallStatusType.Checking;
                        break;
                    case AgentStatusType.None:
                        tmpCallStatus = CallStatusType.None;
                        break;
                    case AgentStatusType.Offline:
                        tmpCallStatus = CallStatusType.Offline;
                        break;
                    case AgentStatusType.Online:
                        tmpCallStatus = CallStatusType.Online;
                        break;
                    case AgentStatusType.Busy:
                        tmpCallStatus = CallStatusType.Busy;
                        break;
                    default:
                        tmpCallStatus = CallStatusType.Failed;
                        break;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public static void Dispose()
        {
            Core.Dispose();
            Core = null;
            IsInited = false;
            UpdateAccountInformation("", "");
            UpdateCompanyInformation("", "");
            UpdateCompanyMembersCancel();
            UpdateVideoConfMembersCancel();
        }

        //Test
        public static void SetDisKey(string key)
        {
            RestAPICommon.KEY = key;
        }

        #endregion

    }

    enum AgentStatusType
    {
        Failed = -3,
        Checking = -2,
        None = -1,
        Offline = 0,
        Online = 1,
        Busy = 2,
    }

    enum MemberStatusType
    {
        Calling = 2,
        Connected = 3,
        Busy = 4,
        DisConnect = 5,
        NoAnswer = 6,
    }

    public enum ConferencStatusType
    {
        Unkow,
        Ready,
        Calling,
        Conferencing,
    }

    public enum ConferencType
    {
        Single,
        Multi,
    }

    public enum CallType
    {
        Voice = 1,
        Video = 2,
    }

    public enum CallStatusType
    {
        Failed = -3,
        Checking = -2,
        None = -1,
        Offline = 0,
        Online = 1,
        Calling = 2,
        Connected = 3,
        Busy = 4,
        DisConnect = 5,
        NoAnswer = 6,
        StartCalling = 12,
        Hangup = 18,
        CallIn = 20,
    }

    public enum NetStatus
    {
        None,
        Good,
        Bad,
    }

    public enum CallStatus
    {
        None,
        ReadyForCall,
        Chatting,
    }

    [Flags]
    public enum AppFeatures
    {
        NONE = 512,
        VIDEOCHAT = 1,
        VIDEOLOOKBACK = 2,
        FENPING = 4,
        CONFCALL = 8,
        SETTING = 256,
    }

    /// <summary>
    /// 服务器类型枚举
    /// </summary>
    public enum ServerType
    {
        /// <summary>
        /// 0 = 未知
        /// </summary>
        None = 0,

        /// <summary>
        /// 1 = 正式环境
        /// </summary>
        ZS = 1,

        /// <summary>
        /// 2 = 紫万阿里云
        /// </summary>
        ALI_ZWAN = 2,

        /// <summary>
        /// 3 = 鼎视环境
        /// </summary>
        ALI_TopVision = 3,

        // 4 = 内网环境

        /// <summary>
        /// 5 = 瞳影华为云环境
        /// </summary>
        HW_TopTrue = 5,
        // 6 = 华为实验室
        // 7 = 伟创力内网
        Customer_Flex_Local = 7,
        // 8 = 伟创力外网
        Customer_Flex = 8,

        /// <summary>
        /// 水土外网 222.178.193.83
        /// </summary>
        ZWAN_WAN = 9,
        // 10 = 水土内网

        /// <summary>
        /// 11 = 佐臻亚马逊
        /// </summary>
        AMZ_ZZ = 11,

        /// <summary>
        /// 上汽通用
        /// </summary>
        Customer_ShangQi = 12,

        /// <summary>
        /// 13 = 合煌
        /// </summary>
        Customer_HeHuang = 13,
        // 100 = 内网
        // 101 = 公网
        /// <summary>
        /// 14 = 合煌
        /// </summary>
        Customer_HeHuang2 = 14,
        /// <summary>
        /// 16 = 鼎视南京.3
        /// </summary>
        Topvision_nanjin = 16,
        /// <summary>
        /// 132 = 鼎视南京.4
        /// </summary>
        Topvision_nanjin2 = 132,
        /// <summary>
        /// 炬星
        /// 新 180.167.253.166
        /// 旧 58.247.114.226
        /// </summary>
        Juxin = 18,
        /// <summary>
        /// 亚玛逊 34.239.56.14
        /// </summary>
        Jorjin_AMZ = 19,

        /// <summary>
        /// 众里外网
        /// </summary>
        ZhongLi = 20,

        /// <summary>
        /// 软通动力
        /// </summary>
        Ruantong = 21,

        /// <summary>
        /// 众里-中铁
        /// </summary>
        ZhongLi_ZT = 22,

        /// <summary>
        /// 软通动力2
        /// </summary>
        Ruantong2 = 23,

        /// <summary>
        /// 中车 外网
        /// </summary>
        ZhongChe = 27,
        /// <summary>
        /// 国网 120.211.156.195
        /// </summary>
        GuoWang = 33,

        /// <summary>
        /// 温州电信
        /// 33.112.8.126
        /// </summary>
        WenZhouDianxing = 34,
        
        /// <summary>
        /// WebRTC测试使用
        /// </summary>
        WebRTC=35,

        /// <summary>
        /// 102 = 内网70
        /// </summary>
        ///        

        LOCAL_70 = 102,

        /// <summary>
        /// 103 = 内网71
        /// </summary>
        LOCAL_71 = 103,
        /// <summary>
        /// 众里
        /// </summary>
        LOCAL_ZL = 104,
        /// <summary>
        /// 众里 10.42.91.6
        /// </summary>
        LOCAL_ZL2 = 105,
        /// <summary>
        /// 众里 10.87.112.200
        /// </summary>
        LOCAL_ZL3 = 107,
        /// <summary>
        /// 炬星
        /// </summary>
        JUXING = 108,
        /// <summary>
        /// 河北国网
        /// 120.211.156.219
        /// </summary>
        HeBeiGuoWang = 130,
        /// <summary>
        /// 武钢
        /// </summary>
        WuGang = 133,
        /// <summary>
        /// 武钢物理机
        /// </summary>
        WuGangLan = 134,
    }

}
